#ifndef COMMON_H
#define COMMON_H

#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <iomanip>

#include "acl/acl.h"

#define SUCCESS 0
#define FAILED 1

#define INFO_LOG(fmt,  args...) fprintf(stdout, "[INFO]   " fmt "\n", ##args)
#define WARN_LOG(fmt,  args...) fprintf(stdout, "[WARN]   " fmt "\n", ##args)
#define ERROR_LOG(fmt, args...) fprintf(stderr, "[ERROR]  " fmt "\n", ##args)

char *ReadFile(const std::string &filePath, size_t &fileSize, void *buffer, size_t bufferSize);
bool WriteFile(const std::string &filePath, const void *buffer, size_t size);

class GemmRunner {
public:
    GemmRunner(uint32_t m, uint32_t n, uint32_t k, aclDataType inputType, aclDataType outputType);

    virtual ~GemmRunner();

    bool Init();

    template<typename T>
    void SetAlpha(T alpha) {
        *reinterpret_cast<T *>(hostAlpha_) = alpha;
    }

    template<typename T>
    void SetBeta(T beta)
    {
        *reinterpret_cast<T *>(hostBeta_) = beta;
    }

    bool PrepareInputs();
    bool RunOp();
    bool WriteOutput();
    void PrintMatrixA();
    void PrintMatrixB();
    void PrintMatrixC();
    bool CopyInput();
    bool CopyOutput();

private:
    uint8_t *devMatrixA_ = nullptr;
    uint8_t *devMatrixB_ = nullptr;
    uint8_t *devMatrixC_ = nullptr;

    uint8_t *hostMatrixA_ = nullptr;
    uint8_t *hostMatrixB_ = nullptr;
    uint8_t *hostMatrixC_ = nullptr;

    uint32_t m_;
    uint32_t n_;
    uint32_t k_;

    uint8_t *devAlpha_    = nullptr;
    uint8_t *devBeta_     = nullptr;
    uint8_t hostAlpha_[8] = {0};
    uint8_t hostBeta_[8]  = {0};

    size_t sizeA_;
    size_t sizeB_;
    size_t sizeC_;
    size_t sizeAlphaBeta_;

    aclDataType inputType_;
    aclDataType outputType_;
};

#endif // COMMON_H
